home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 37
/
Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso
/
Aminet
/
dev
/
cross
/
devpic.lha
/
devpic
/
source
/
picprog.c
next >
Wrap
C/C++ Source or Header
|
2000-04-03
|
16KB
|
669 lines
#include <exec/memory.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/misc_protos.h>
#include <clib/timer_protos.h>
#include <pragmas/exec_sysbase_pragmas.h>
#include <pragmas/timer_pragmas.h>
#include <pragmas/misc_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <resources/misc.h>
#include <dos/dos.h>
struct Library *DOSBase, *SysBase, *TimerBase, *MiscBase;
struct MsgPort *timereplyport;
struct timerequest *timereq;
__far struct FileInfoBlock fib;
struct {
STRPTR from;
ULONG* force;
ULONG* smartflash;
ULONG* configword;
ULONG verify;
} arg = { 0, 0, 0, 0, 0 };
#define TEMPLATE "FROM/A,FORCE/N,SF=SMARTFLASH/N,CW=CONFIGWORD/N,V=VERIFY/S"
STRPTR inpoint;
static ULONG pvout, psout;
ULONG rc;
__far static UWORD deltabuf[8192];
UBYTE unhex(void);
UBYTE unhexbyte(void);
ULONG picReadCode(void);
ULONG picRecv(ULONG);
ULONG picSetup(void);
void picCmd(ULONG);
void picSend(ULONG, ULONG);
void picWait(ULONG);
void picInc(void);
void picIncNum(ULONG);
void picEnterProgMode(void);
void picUndocmd(void);
void picEraseProg(ULONG);
void picProgOnly(ULONG);
void picCleanup(void);
void picLoadCode(ULONG);
void picLoadConf(ULONG);
enum {
LOADCONF = 0,
UNDOC1,
LOADCODE,
LOADDATA,
READCODE,
READDATA,
INCADDR,
UNDOC2,
BEGINPROG,
ERASECODE,
ERASEDATA = 11,
PROGONLY = 24
};
__saveds main()
{
SysBase = *((struct Library **)4L);
rc = 20;
if(DOSBase = OpenLibrary("dos.library",36))
{
if(timereplyport = CreateMsgPort()) // ReplyPort for time requests
{
if(timereq = (struct timerequest *)CreateIORequest(timereplyport,sizeof(struct timerequest)))
{
if(!OpenDevice(TIMERNAME,UNIT_MICROHZ,(struct IORequest *)timereq,0))
{
struct RDArgs *rda;
Printf("%s © Russian Digital Computing\n",6+"$VER: picprog 1.4 "__AMIGADATE__);
if(rda = ReadArgs(TEMPLATE,(LONG *)&arg,NULL))
{
BPTR infile;
if(infile = Open(arg.from,MODE_OLDFILE))
{
STRPTR indata;
ExamineFH(infile,&fib);
if(inpoint = indata = AllocVec(fib.fib_Size+1000,MEMF_CLEAR))
{
*(indata+fib.fib_Size+998) = 0x0A;
if(-1!=Read(infile,indata,fib.fib_Size))
{
ULONG end = 0, erc = 0, nl = 0;
ULONG line = 0, actualen = 0, lastaddr = 0;
while(TRUE)
{
line++;
if(':'==*inpoint)
{
STRPTR checkpoint = ++inpoint;
UBYTE len = unhex();
UBYTE hiaddr = unhex();
UBYTE loaddr = unhex();
UBYTE type = unhex();
UBYTE sum = len + loaddr + hiaddr + type;
ULONG checklen = (len+5)<<1;
while(checklen--)
{
UBYTE tb = *checkpoint++;
if((tb<'0')||
(tb>'f')||
((tb>'9')&&(tb<'A'))||
((tb>'F')&&(tb<'a')))
{
erc = 3;
goto hexend;
}
}
switch(type)
{
case 0: //data
{
ULONG fulladdr = (hiaddr<<8) + loaddr;
if(lastaddr!=fulladdr)
{
nl=1;
}
lastaddr = fulladdr+len;
if(lastaddr>actualen)
{
actualen=lastaddr;
}
while(len--) sum += unhex();
if((UBYTE)(sum+unhex()))
{
erc = 1;
goto hexend;
}
break;
}
case 1: //EOF
{
if(loaddr|hiaddr|len) //it is not a typo
{
erc = 3;
goto hexend;
}
if((UBYTE)(sum+unhex()))
{
erc = 1;
}
end = 1;
goto hexend;
}
case 2: //segment address
case 3: //segment start address
case 4: //linear address
case 5: //linear start address
{
erc = 3;
goto hexend;
}
default:
{
erc = 2;
goto hexend;
}
}
}
while((0x0A!=*inpoint)&&(0x0D!=*inpoint))
{
inpoint++;
}
if((0x0D==*inpoint)&&(0x0A==inpoint[1]))
{
inpoint++;
}
if((inpoint++)>(indata+fib.fib_Size))
{
break;
}
}
hexend:
if(erc)
{
static STRPTR errtxt[] = {
"Checksum error at",
"Unknown record type at",
"Invalid",
"Unsupported record type (useless for PIC16 object files) at" };
Printf("%s line %ld\n",errtxt[erc-1],line);
if(!actualen)
{
Printf("Possibly n%s","ot an !ntel Hex file\n");
}
}
else
{
if(actualen)
{
if(end)
{
STRPTR outdata = inpoint = indata;
ULONG outmem = 0;
if(nl)
{
//Printf("Warning: non-linear file\n");
if(outdata = AllocVec(actualen,MEMF_ANY))
{
ULONG count = actualen;
STRPTR fillpoint = outdata;
while(count--)
{
*fillpoint++ = 0xff;
}
outmem = 1;
}
else
{
Printf("Can't allocate memory for output file\n");
}
}
if(outdata)
{
UWORD *wordbuf = (UWORD*)outdata;
ULONG wc = actualen>>1, wordcount, word;
ULONG wordswritten = 0;
if(wc>8192)
{
wc=8192;
}
while(':'==*inpoint++)
{
UBYTE len = unhex();
UBYTE hiaddr = unhex();
UBYTE loaddr = unhex();
UBYTE type = unhex();
if(!type)
{
STRPTR outpoint = outdata + (hiaddr<<8) + loaddr;
while(len--) *outpoint++ = unhex();
}
inpoint += 2;
while('!'>*inpoint) inpoint++;
}
// PIC16Fxxx PROGRAMMING START
if(picSetup())
{
picEnterProgMode();
if(arg.force)
{
picLoadConf(*arg.force); //0x3ffa äëÿ 16f84, 0x3f3a äëÿ 16f876
picIncNum(7);
picUndocmd();
picEraseProg(10);
picUndocmd();
picEnterProgMode();
}
word = 0;
wordcount = wc;
if(arg.smartflash)
{
ULONG words = 0, wordiff = 0;
if(arg.force)
{
words++;
wordiff++;
}
else
{
while(wordcount--)
{
UWORD val = (*wordbuf>>8)|(*wordbuf<<8);
if(!(0xC000 & val))
{
if(val != (deltabuf[word] = picReadCode()))
{
wordiff++;
}
words++;
}
picInc();
wordbuf++;
word++;
}
}
if(wordiff)
{
picEnterProgMode();
word = 0;
wordcount = wc;
wordbuf = (UWORD*)outdata;
if((wordiff<<1)>words)
{
picLoadCode(0xffff);
picCmd(ERASECODE);
picEraseProg(10);
picEnterProgMode();
while(wordcount--)
{
UWORD val = (*wordbuf>>8)|(*wordbuf<<8);
if(!(0xC000 & val))
{
ULONG tempdat;
picLoadCode(val);
picProgOnly(*arg.smartflash);
tempdat = picReadCode();
if(val != tempdat)
{
Printf("Error writing location %ld\n",word);
Printf("must be %lx but read %lx\n",val,tempdat);
goto picerr;
}
wordswritten++;
}
picInc();
wordbuf++;
word++;
}
}
else
{
while(wordcount--)
{
UWORD val = (*wordbuf>>8)|(*wordbuf<<8);
if(!(0xC000 & val))
{
if(val != deltabuf[word])
{
ULONG tempdat;
picLoadCode(val);
picEraseProg((*arg.smartflash)<<1);
tempdat = picReadCode();
if(val != tempdat)
{
Printf("Error writing location %ld\n",word);
Printf("must be %lx but read %lx\n",val,tempdat);
goto picerr;
}
wordswritten++;
}
}
picInc();
wordbuf++;
word++;
}
}
}
}
else
{
while(wordcount--)
{
UWORD val = (*wordbuf>>8)|(*wordbuf<<8);
ULONG tempdat;
if(!(0xC000 & val))
{
tempdat = picReadCode();
if(val != tempdat)
{
picLoadCode(val);
picEraseProg(10);
tempdat = picReadCode();
if(val != tempdat)
{
Printf("Error writing location %ld\n",word);
Printf("must be %lx but read %lx\n",val,tempdat);
goto picerr;
}
wordswritten++;
}
}
picInc();
wordbuf++;
word++;
}
}
if(arg.verify)
{
wordbuf = (UWORD*)outdata;
picEnterProgMode();
word = 0;
wordcount = wc;
while(wordcount--)
{
UWORD val = (*wordbuf>>8)|(*wordbuf<<8);
ULONG tempdat;
if(!(0xC000 & val))
{
if(val != (tempdat=picReadCode()))
{
Printf("Verify error at location %ld\n",word);
Printf("must be %lx but read %lx\n",val,tempdat);
goto picerr;
}
}
picInc();
wordbuf++;
word++;
}
}
if(arg.configword)
{
picLoadConf(*arg.configword);
picIncNum(7);
if((*arg.configword) != picReadCode())
{
picLoadCode(*arg.configword);
picEraseProg(10);
if((*arg.configword) != picReadCode())
{
Printf("Error writing configuration word\n");
goto picerr;
}
wordswritten++;
}
}
rc = 0;
if(wordswritten)
{
Printf("Programming finished, %ld location%s done\n",wordswritten,wordswritten>1?"s":1+"s");
}
else
{
Printf("No differencies - nothing to do!\n");
}
picerr:
picCleanup();
}
// PIC16Fxxx PROGRAMMING END
if(outmem)
{
FreeVec(outdata);
}
}
}
else
{
Printf("EOF record not found\n");
}
}
else
{
if(end)
{
Printf("File does not contain any data\n");
}
else
{
Printf("N%s","ot an !ntel Hex file\n");
}
}
}
}
FreeVec(indata);
}
else
{
Printf("Can't allocate memory for input file\n");
}
Close(infile);
}
else
{
Printf("Can't open source file\n");
}
FreeArgs(rda);
}
else
{
Printf("Error in arguments\n");
}
CloseDevice((struct IORequest *)timereq);
}
else
{
Printf("Can't open %s\n",TIMERNAME);
}
DeleteIORequest((struct IORequest *)timereq);
}
else
{
Printf("Can't create IORequest\n");
}
DeleteMsgPort(timereplyport);
}
else
{
Printf("Can't create msgport\n");
}
CloseLibrary(DOSBase);
}
return(rc);
}
UBYTE unhex(void)
{
return((UBYTE)((unhexbyte()<<4)+unhexbyte()));
}
UBYTE unhexbyte(void)
{
if(*inpoint<='9')
{
return((UBYTE)((*inpoint++)-'0'));
}
return((UBYTE)(((*inpoint++)|32)-'a'+10));
}
/**************************/
/* */
/* HARDWARE INTERFACE */
/* */
/**************************/
#define PORTVALUE *((STRPTR)0xbfe101)
#define PORTSTATE *((STRPTR)0xbfe301)
#define BSET(val,bit) val|=(1<<bit)
#define BCLR(val,bit) val&=(~(1<<bit))
#define BTST(val,bit) val & (1<<bit)
ULONG picSetup(void)
{
if(MiscBase = OpenResource(MISCNAME))
{
STRPTR owner;
if(owner = AllocMiscResource(MR_PARALLELPORT,"PIC programmer"))
{
Printf("Can't allocate parallel port - it is owned by %s\n",owner);
return(0);
}
else return(1);
}
else
{
Printf("Can't open %s\n",MISCNAME);
return(0);
}
}
void picCleanup(void)
{
psout = 4+8+16;
PORTSTATE = psout;
pvout = 4;
PORTVALUE = pvout;
pvout = 8+16;
PORTVALUE = pvout;
FreeMiscResource(MR_PARALLELPORT);
}
void picCmd(ULONG cmd)
{
picSend(cmd,6);
}
void picInc(void)
{
picSend(INCADDR,6);
}
void picIncNum(ULONG num)
{
while(num--)
{
picInc();
}
}
void picUndocmd(void)
{
picCmd(UNDOC1);
picCmd(UNDOC2);
}
void picEraseProg(ULONG time)
{
picCmd(BEGINPROG);
picWait(time);
}
void picProgOnly(ULONG time)
{
picCmd(PROGONLY);
picWait(time);
}
void picWait(ULONG time)
{
timereq->tr_node.io_Command = TR_ADDREQUEST;
timereq->tr_time.tv_secs = 0;
timereq->tr_time.tv_micro = time*1000;
DoIO((struct IORequest *)timereq);
}
ULONG picReadCode(void)
{
picCmd(READCODE);
return(0x3fff&(picRecv(16)>>1));
}
void picLoadCode(ULONG data)
{
picCmd(LOADCODE);
picSend(data<<1,16);
}
void picLoadConf(ULONG data)
{
picCmd(LOADCONF);
picSend(data<<1,16);
}
void picSend(ULONG val, ULONG bits)
{
BSET(psout,0);
PORTSTATE = psout;
while(bits--)
{
BSET(pvout,1);
if(BTST(val,0))
{
BSET(pvout,0);
}
else
{
BCLR(pvout,0);
}
PORTVALUE = pvout;
BCLR(pvout,1);
PORTVALUE = pvout;
val >>= 1;
}
}
ULONG picRecv(ULONG bits)
{
ULONG val = 0;
BCLR(psout,0);
PORTSTATE = psout;
while(bits--)
{
BSET(pvout,1);
PORTVALUE = pvout;
BCLR(pvout,1);
PORTVALUE = pvout;
val >>= 1;
if(BTST(PORTVALUE,0))
{
BSET(val,15);
}
}
return(val);
}
void picEnterProgMode(void)
{
psout = 1+2+4+8+16;
PORTSTATE = psout;
pvout = 0;
PORTVALUE = pvout;
BSET(pvout,2);
PORTVALUE = pvout;
BCLR(pvout,2);
PORTVALUE = pvout;
}